home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / yerk / mps231ss.hqx / Mops source / Toolbox classes / PrintManager < prev    next >
Text File  |  1992-07-25  |  7KB  |  254 lines

  1.     \ 24Jul92 DBH
  2.  
  3. \ note that dlen from the source file class was redefined as a value in
  4. \ the source file struct
  5. : DataLength    ( ^class -- n )  \ given a pointer to a class, return the
  6.                                  \ length of the ivar data
  7.     dlen&xwid drop ;
  8.  
  9.  
  10. \ define the non-trivial toolbox calls as normal words, not required, but
  11. \ this makes it easier to follow the methods, I think
  12.  
  13. : PrValidate  { thPrint -- b }
  14.     word0 thPrint call PrValidate i->l ;
  15.     
  16. : PrStlDialog  { thPrint -- b }
  17.     word0 thPrint call PrStlDialog i->l ;
  18.     
  19. : PrJobDialog  { thPrint -- b }
  20.     word0 thPrint call PrJobDialog i->l ;
  21.     
  22. : PrOpenDoc { thPrint tpPrPort tpIOBuf -- TPPrPort }
  23.     0 thPrint tpPrPort tpIOBuf call PrOpenDoc ;
  24.     
  25. : PrError ( -- errorCode )
  26.     word0 call PrError i->l ;
  27.  
  28. \ now define some classes for the purpose of mapping into the Mac records
  29.  
  30. :class TPrInfo    super{ object }
  31.     int        iDev
  32.     int        iVRes    \ vertical resolution of printer
  33.     int        iHRes    \ horizontal resolution of printer
  34.     rect    rPage    \ page rectangle
  35. ;class
  36.  
  37.  
  38. :class TPrStl    super{ object }
  39.     int        wDev    \ high byte specifies device (1=ImageWriter, 3=LaserWriter)
  40.     6 bytes junk    \ more fields for internal use, not mapped
  41. ;class
  42.  
  43.  
  44. :class TPrJob  super{ object }
  45.     int        iFstPage
  46.     int        iLstPage
  47.     int        iCopies
  48.     byte    bJDocLoop    \ print method, 0=draft  1=spooled
  49.     bool    fFromUsr
  50.     ptr        pIdleProc    \ background procedure
  51.     ptr        pFileName
  52.     4 bytes junk
  53.  
  54. :m spooled?:    ( -- b)
  55.     get: bJDocLoop  1 = ;m
  56.  
  57. ;class
  58.  
  59.  
  60. :class THPrint    super{ object }
  61.     int            iPrVersion
  62.     TPrInfo        prInfo
  63.     rect        rPaper
  64.     TPrStl        prStl
  65.     TPrInfo        prInfoPT
  66.     16 bytes    prXInfo        \ not mapped due to very limited use
  67.     TPrJob        prJob
  68.     38 bytes    printX
  69.  
  70. :m spooled?:    ( -- b)
  71.     spooled?: prJob ;m
  72.  
  73. ;class
  74.  
  75.  
  76. :class  TPrStatus  super{ object }
  77.     int        iTotPages        \ number of pages in spool file
  78.     int        iCurPage        \ page being printed
  79.     int        iTotCopies        \ number of copies requested
  80.     int        iCurCopy        \ copy being printed
  81.     int        iTotBands        \ used internally
  82.     int        iCurBand        \ used internally
  83.     bool    fPgDirty        \ true if started printing page
  84.     bool    fImaging        \ used internally
  85.     handle    hPrint            \ print record
  86.     var        pPrPort            \ printing grafport
  87.     handle    hPic            \ used internally
  88. ;class
  89.  
  90.  
  91. :class PrintManager super{ object }
  92.     
  93.     handle         hPrint
  94.     TPrStatus    prStatus
  95.     x-addr        draw    \ draw handler for printing
  96.     
  97.  
  98. :m put:    ( cfa -- )
  99.     put: draw ;m
  100.  
  101. :m new:        \ must call new: only once at runtime to allocate print record
  102.     ['] THPrint DataLength  new: hPrint ;m
  103.  
  104. :m getnew:    \ this method should obtain a print record from the resource
  105.     \ fork of the file, if a file exists that is ( see PageSetup: comments
  106.     \ and see IM II-150 Note: )
  107.     \ This method is not implemented here, but would be used in place of new:.
  108.     ;m
  109.  
  110. :m release:
  111.     release: hPrint ;m
  112.  
  113. :m PageSetup:    ( -- b)    \ rundialog, returns 0 if user cancel
  114.     \ if user did not cancel, it might be a good idea to save the hprint record
  115.     \ to disk so the printing parameters chosen by the user can be restored.
  116.     \ But this restoration is not automatic and must be done by the program.
  117.     call PrOpen
  118.     PrError 0=
  119.     IF
  120.         get: hPrint PrStlDialog
  121.     THEN
  122.     call PrClose ;m
  123.  
  124. private
  125.  
  126. \ note, only printing one page here ( so this isn't really a loop)
  127. :m printLoop:    { \ pPrPort -- }
  128.     get: hPrint 0 0 PrOpenDoc -> pPrPort
  129.     PrError 0=
  130.     IF
  131.         pPrPort 0 call PrOpenPage    \ pPageFrame=0, so no scaling
  132.         PrError 0=
  133.         IF
  134.             exec: draw
  135.         THEN
  136.         pPrPort call PrClosePage
  137.     THEN
  138.     pPrPort call PrCloseDoc
  139.     
  140.     PrError 0=
  141.     ptr: hPrint  spooled?: THPrint  and        \ note message to class THPrint
  142.         IF
  143.             get: hPrint 0 0 0 addr: prStatus call PrPicFile
  144.         THEN
  145. ;m
  146.     
  147. public
  148.  
  149. :m Print:
  150.     call PrOpen
  151.     PrError 0=
  152.     IF
  153.         pushport
  154.         
  155.         get: hPrint PrJobDialog
  156.         IF printLoop: self THEN
  157.         
  158.         popport
  159.     THEN
  160.     call PrClose ;m
  161.  
  162. ;class
  163.  
  164. PrintManager  pm    \ instantiate an object, named pm, to do all printing work
  165.  
  166. endload
  167.  
  168.  
  169.  
  170.  
  171. ********* Example usage of Print Manager **********
  172.  
  173. : testPrint
  174.     30 30 80 80 put: temprect
  175.     draw: temprect ;
  176.  
  177. ' testPrint put: pm        \ put the draw action in our PrintManager object
  178.  
  179.  
  180. new: pm                    \ must always call new: only once at runtime
  181.  
  182. PageSetup: pm .            \ not required, but does what it says
  183. Print: pm                \ let er rip
  184.  
  185. release: pm            \ not required till quitting, i.e. can do multiple Print:'s
  186.                     \ without calling this.  This just releases some memory.
  187.  
  188.  
  189.  
  190. ****** Possible Enhancements ********
  191.  
  192. Of course, we need to cycle through and print each requested page.
  193.  
  194. I think a better printing model could be achieved by having a " print object"
  195. instance variable in the PrintManager class.  It would simply be sent a 
  196. print: message at the correct time, rather than sending exec: to an x-addr
  197. as is done here.  I think it would be more flexible and robust to have the
  198. PrintManager object communicate with a print object.
  199.  
  200. It would probably make sense to have printing be a function of the
  201. page rectangle and page number.  So the print object would always
  202. be passed this information when a page is requested to be drawn.
  203. And probably the message should be PrintPage: with the rectangle and
  204. page number passed as parameters to the print object.
  205.  
  206. Also, a way to easily save and restore the the page setup parameters in a
  207. file's resource fork would be nice.  See suggested message getnew:.
  208.  
  209. SInce no background procedure is provided, the toolbox will default to
  210. cancelling upon command-period.  See IM II-152,153.  But it shouldn't be
  211. difficult to provide a custom background procedure.
  212.  
  213.  
  214. ****** Comments *******
  215.  
  216. Note the use of a class definition to map into a toolbox-created record,
  217. in this case the THPrint record.  In the printLoop: method of class PrintManager
  218. we need to access a member of a record that is contained in a subrecord, in
  219. this case bjDocLoop (member of TPrJob, which is a subrecord of THPrint).
  220. Now we could have simply obtained the pointer to the print record, added
  221. the correct offset, and performed a c@:
  222.  
  223.     ptr: hPrint  offset + c@
  224.     
  225. But there are some problems with this approach, even though it may seem more
  226. straightforward.  First, one must compute the offset.  I have no idea what it
  227. is, nor do I wish to know.  Second, one must remember to perform the correct
  228. type of "fetch" (c@ here, or was it c@x?).  Thirdly, I don't think it is very
  229. clear what is going on here.
  230.  
  231. Instead, I believe a better approach is to define the records as classes,
  232. define the required access methods, and then pass a message to a class with
  233. the appropriate base address on the stack:
  234.  
  235.     ptr: hPrint   spooled?: THPrint
  236.  
  237. Here the spooled?: message will be passed by class THPrint to its prJob ivar
  238. which will obtain the value of bjDocLoop contained in the record pointed to
  239. by  ptr: hPrint.
  240.  
  241. One must be careful when passing a message to a class that the address
  242. on the stack really does point to a data structure that matches the class.
  243. The offset (to bjDocLoop) is automatically computed, the appropriate "fetch"
  244. is automatically performed, and it is very clear what is going on.  Also,
  245. one does not need to know the length of the THPrint record when allocating
  246. memory for the handle hPrint.  Merely passing the class pointer to DataLength
  247. will do that job  ( see definition of DataLength at the beginning of this file)
  248. as in the new: method for PrintManager.
  249.  
  250.  
  251.  
  252. Doug Hoffman      24Jul92
  253.  
  254. Compuserve 72310,1743